package com.gt.handler;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gt.data.GlobalData;
import com.gt.vo.BossDataVo;
import com.gt.vo.FightRecordDataVo;
import com.gt.vo.UserRecordDataVo;
import com.gt.vo.UserVo;
import com.spire.xls.Workbook;
import com.spire.xls.Worksheet;
import net.mamoe.mirai.event.events.GroupMessageEvent;
import net.mamoe.mirai.event.events.MessageEvent;
import net.mamoe.mirai.message.data.At;
import net.mamoe.mirai.message.data.Image;
import net.mamoe.mirai.message.data.PlainText;
import net.mamoe.mirai.message.data.SingleMessage;
import net.mamoe.mirai.utils.ExternalResource;

import java.io.File;
import java.util.*;

public class QQMessageHandler {

    public static void handle(MessageEvent messageEvent){
        if(messageEvent instanceof GroupMessageEvent){
            GroupMessageEvent event = (GroupMessageEvent) messageEvent;
            //自己说的消息 过滤
            if(event.getSender().getId() == event.getBot().getId()){
                return;
            }
            boolean isAtMe = false;
            String message = "";
            for(SingleMessage msg : event.getMessage()){
                if(msg instanceof At){
                    At at = (At)msg;
                    if(at.getTarget() == event.getBot().getId()){
                        isAtMe = true;
                    }
                }else if(msg instanceof PlainText){
                    PlainText plainText = (PlainText)msg;
                    message += plainText.getContent();
                }
            }
            if(!isAtMe){
                //如果非显示@我 检查文本是否@我
                if(message.indexOf("@"+event.getBot().getNick()) != -1){
                    isAtMe = true;
                }
            }
            message = StrUtil.replace(message,"@"+event.getBot().getNick(),"");
            message = StrUtil.trim(message);
            Console.log("isAtMe-->"+isAtMe+",message-->"+message);
            if(!isAtMe){
                //非@我的消息过滤
                return;
            }
            if(StrUtil.indexOfIgnoreCase(message,"会战统计") != -1){
                String imgpath = huiZhanTongJi();
                File file = new File(imgpath);
                if(file.exists()){
                    Image image = event.getGroup().uploadImage(ExternalResource.create(file));
                    String imageId = image.getImageId(); // 可以拿到 ID
                    Image fromId = Image.fromId(imageId);
                    event.getGroup().sendMessage(image);//发送图片
                }
            }else{
                String question = StrUtil.replace(message,"@"+event.getBot().getNick(),"");
                question = question.trim();
                String answer = botAutoAnswer(question,event.getSender().getNick());
                event.getGroup().sendMessage(new At(event.getSender().getId()).plus(answer));
            }
        }
    }

    /**
     * 机器人自动应答
     * @param question
     * @param askerName
     * @return
     */
    public static String botAutoAnswer(String question,String askerName){
        try {
            String url = "http://i.itpk.cn/api.php?question="+question;
            String rs = HttpUtil.get(url);
            if(rs.startsWith("\uFEFF")){
                rs = StrUtil.subAfter(rs,"\uFEFF",false);
            }
            if(rs.startsWith("{")){
                JSONObject json = JSON.parseObject(rs);
                rs = json.getString("content");
            }
            rs = StrUtil.replace(rs,"[cqname]","我");
            rs = StrUtil.replace(rs,"[name]",askerName);
            return rs;
        } catch (Exception e) {
            Console.error(e);
        }
        return "啥?";
    }

    /**
     * 生成会战统计图片
     * @return 图片路径
     */
    public synchronized static String huiZhanTongJi(){
        ClassPathResource resource = new ClassPathResource("小公主集团会战统计.xlsx");
        String filepath = resource.getFile().getPath();
        Console.log(filepath);
        //加载Excel工作表
        Workbook wb = new Workbook();
        wb.loadFromFile(filepath);

        //获取工作表
        Worksheet sheet = wb.getWorksheets().get(0);
        String session = GlobalData.getValue("session-api"); //从网页使用F12获取 https://www.bigfun.cn/tools/gt/t_report

        //1.获取所有记录
        BossDataVo bossDataVo = fetchBossDataVo(session);
        FightRecordDataVo fightRecordDataVo = fetchFightRecordDataVo(session);
        Date[] dates = GlobalData.fetchHuizhanBeginAndEndTime();
        String time1 = DateUtil.formatDate(dates[0]);
        String time2 = DateUtil.formatDate(dates[1].getTime() > System.currentTimeMillis() ? new Date() : dates[1]);
        List<UserRecordDataVo.UserRecordVo> userRecordVos = fetchUserRecordDataVo(session,time1,time2);
        //2.整理数据到fightRecordDataVo
        for(FightRecordDataVo.FightRecordVo record : fightRecordDataVo.data){
            int damage = record.damage;
            long log_time = record.log_time;
            String boss_name = record.boss.name;
            for(UserRecordDataVo.UserRecordVo userRecordVo : userRecordVos){
                boolean needBreak = false;
                for(UserRecordDataVo.UserRecordVo.DamageVo damageVo : userRecordVo.damage_list){
                    boolean check1 = damage == damageVo.damage;
                    boolean check2 = log_time == damageVo.log_time;
                    boolean check3 = boss_name.equals(damageVo.boss_name);
                    if(check1 && check2 && check3){
                        record.user_id = userRecordVo.user_id;
                        record.damageVo = damageVo;
                        needBreak = true;
                        break;
                    }
                }
                if(needBreak){
                    break;
                }
            }
        }
        //3.检查
        for(FightRecordDataVo.FightRecordVo record : fightRecordDataVo.data){
            if(record.damageVo == null){
                Console.log("检查到数据不完整,user_name:{},boss:{},时间戳:{},伤害:{}",record.user_name,record.boss.name,record.log_time,record.damage);
            }
        }
        //4.统计boss出刀次数
        Map<Integer,Integer> bossDamageCountMap = new HashMap<>();
        for(FightRecordDataVo.FightRecordVo record : fightRecordDataVo.data){
            if(record.damageVo == null){
                continue;
            }
            Integer count = bossDamageCountMap.get(record.damageVo.boss_id);
            count = count == null ? 0 : count;
            count += 1;
            bossDamageCountMap.put(record.damageVo.boss_id,count);
        }
        //5.统计
        Map<Long, UserVo> userMap = new HashMap<>();
        for(FightRecordDataVo.FightRecordVo record : fightRecordDataVo.data){
            UserVo userVo = userMap.get(record.user_id);
            if(userVo == null){
                userVo = new UserVo();
                userVo.user_id = record.user_id;
                userVo.user_name = record.user_name;
                userMap.put(record.user_id,userVo);
            }
            UserVo.BossDamageVo userBossDamageVo = userVo.bossDamageMap.get(record.boss.name);
            if(userBossDamageVo == null){
                userBossDamageVo = new UserVo.BossDamageVo();
                userBossDamageVo.boss_name = record.boss.name;
                userVo.bossDamageMap.put(record.boss.name,userBossDamageVo);
            }
            //总伤害
            userVo.totalDamage += record.damage;
            userBossDamageVo.totalDamage += record.damage;
            //总刀数
            userBossDamageVo.damageCount += 1;
            userVo.damageCount += 1;
            //是否尾刀
            if(record.damageVo != null && record.damageVo.is_kill == 1){
                if(bossDamageCountMap.get(record.damageVo.boss_id) > 1){
                    userVo.tailDamageCount += 1;
                    userBossDamageVo.tailDamageCount += 1;
                }
            }
        }
        //6.排序
        UserVo[] userVos = userMap.values().toArray(new UserVo[0]);
        for(BossDataVo.BossVo bossVo : bossDataVo.boss){
            String bossName = bossVo.name;
            Arrays.sort(userVos, new Comparator<UserVo>() {
                @Override
                public int compare(UserVo o1, UserVo o2) {
                    UserVo.BossDamageVo bossDamageVo1 = o1.bossDamageMap.get(bossName);
                    UserVo.BossDamageVo bossDamageVo2 = o2.bossDamageMap.get(bossName);
                    if(bossDamageVo1 == null){
                        return 1;
                    }
                    if(bossDamageVo2 == null){
                        return -1;
                    }
                    return (int)(bossDamageVo2.totalDamage - bossDamageVo1.totalDamage);
                }
            });
            for(int i = 0; i < userVos.length ;i++){
                UserVo.BossDamageVo bossDamageVo = userVos[i].bossDamageMap.get(bossName);
                if(bossDamageVo == null){
                    bossDamageVo = new UserVo.BossDamageVo();
                    bossDamageVo.boss_name = bossName;
                    userVos[i].bossDamageMap.put(bossName,bossDamageVo);
                }
                bossDamageVo.rank = i + 1;
            }
        }
        Arrays.sort(userVos, new Comparator<UserVo>() {
            @Override
            public int compare(UserVo o1, UserVo o2) {
                return (int)(o2.totalDamage - o1.totalDamage);
            }
        });
        for(int i = 0; i < userVos.length ;i++){
            userVos[i].rank = i + 1;
        }
        //输出到excel
        for(int i = 0 ; i < bossDataVo.boss.size();i++){
            BossDataVo.BossVo bossVo = bossDataVo.boss.get(i);
            sheet.getCellRange(1,3 + i).setText(bossVo.name+"("+bossVo.elemental_type_cn+")");
        }
        for(int i = 0; i < userVos.length ;i++){
            UserVo userVo = userVos[i];
            sheet.getCellRange(i+2,1).setText(userVo.user_name);
            sheet.getCellRange(i+2,2).setText(StrUtil.format("伤害：{}\n刀数：{}\n排名：{}\n尾刀：{}",userVo.totalDamage,userVo.damageCount,userVo.rank,userVo.tailDamageCount));
            for(int j = 0 ; j < bossDataVo.boss.size();j++){
                BossDataVo.BossVo bossVo = bossDataVo.boss.get(j);
                UserVo.BossDamageVo bossDamageVo = userVo.bossDamageMap.get(bossVo.name);
                sheet.getCellRange(i+2,3 + j).setText(StrUtil.format("伤害：{}\n刀数：{}\n排名：{}\n尾刀：{}",bossDamageVo.totalDamage,bossDamageVo.damageCount,bossDamageVo.rank,bossDamageVo.tailDamageCount));
            }
        }
        for(int i = userVos.length + 2;i<=40;i++){
            sheet.getCellRange(i,1).setText("");
        }
        String dir = "/tmp/gt/";
        String fileName = ""+System.currentTimeMillis()+".png";
        FileUtil.mkdir(dir);
        String filePath = dir + fileName;
        sheet.saveToImage(filePath,1,1,1+userVos.length,6);
        //保存excel
        wb.save();
        return filePath;
    }

    public static FightRecordDataVo fetchFightRecordDataVo(String session){
        String url = "https://www.bigfun.cn/api/feweb?target=kan-gong-guild-log%2Fa&date=&user_id=&page=1&size=2000";
        String result = HttpRequest.get(url)
                .cookie("session-api="+session)
                .timeout(5000)
                .execute()
                .body();
        FightRecordDataVo fightRecordDataVo = JSON.parseObject(result, FightRecordDataVo.class);
        return fightRecordDataVo;
    }

    public static BossDataVo fetchBossDataVo(String session){
        String url = "https://www.bigfun.cn/api/feweb?target=kan-gong-guild-boss-info%2Fa";
        String result = HttpRequest.get(url)
                .cookie("session-api="+session)
                .timeout(5000)
                .execute()
                .body();
        JSONObject object = JSON.parseObject(result);
        JSONObject data = object.getJSONObject("data");
        BossDataVo bossDataVo = JSON.toJavaObject(data,BossDataVo.class);
        Console.log("boss数量:{},当前轮数:{}",bossDataVo.boss.size(),bossDataVo.round);
        return bossDataVo;
    }

    public static List<UserRecordDataVo.UserRecordVo> fetchUserRecordDataVo(String session, String fromDate, String endDate){
        String url = "https://www.bigfun.cn/api/feweb?target=kan-gong-guild-report%2Fa&date=";
        List<UserRecordDataVo.UserRecordVo> list = new ArrayList<>();
        Date fromTime = DateUtil.parse(fromDate);
        Date toTime = DateUtil.parse(endDate);
        while(true){
            if(fromTime.getTime() > toTime.getTime()){
                break;
            }
            String dateStr = DateUtil.formatDate(fromTime);
            String url2 = url + dateStr;
            String result = HttpRequest.get(url2)
                    .cookie("session-api="+session)
                    .timeout(5000)
                    .execute()
                    .body();
            UserRecordDataVo userRecordDataVo = JSON.parseObject(result, UserRecordDataVo.class);
            list.addAll(userRecordDataVo.data);
            Console.log("日期:{},出刀人数:{}",dateStr,userRecordDataVo.data.size());
            fromTime = DateUtil.offsetDay(fromTime,1);
        }
        return list;
    }
}
